package org.spider.core.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerUtils;
import org.quartz.spi.OperableTrigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spider.api.domain.vo.SpiderFlowVo;
import org.spider.api.domain.model.HistoryConfig;
import org.spider.api.domain.model.SpiderFlow;
import org.spider.api.enums.CronEnableType;
import org.spider.api.utils.MyDateUtil;
import org.spider.api.utils.flow.SpiderFlowUtils;
import org.spider.core.job.SpiderJobManager;
import org.spider.core.mapper.FlowMapper;
import org.spider.core.mapper.TaskMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author Junjie
 * @description 针对表【flow】的数据库操作Service实现
 * @createDate 2024-01-16 15:10:39
 */
@Service
public class SpiderFlowService extends ServiceImpl<FlowMapper, SpiderFlow> {
    @Resource
    private FlowMapper flowMapper;
    @Resource
    private HistoryConfigService historyConfigService;
    @Resource
    private SpiderJobManager spiderJobManager;
    private final static Logger logger = LoggerFactory.getLogger(SpiderFlowService.class);

    public static final String singleQuotes = "&#39;";



    public IPage<SpiderFlowVo> selectPage(Page<SpiderFlowVo> page,String name){
        return flowMapper.selectPage(page,name);
    }

    //当保存时，应该在历史配置表中插入一条记录
    public boolean saveOrUpdateFlow(SpiderFlow flow) {
        if (flow == null) return false;
        flow.setConfig(SpiderFlowUtils.simpleJson(flow.getConfig()));
        //不为Null，说明之前有值，当前操作为更新
        if (StringUtils.isNotEmpty(flow.getId())) {
            this.updateById(flow);
            //定时任务处理
            spiderJobManager.remove(flow.getId()); //有则移除
            if(flow.getCronEnable()== CronEnableType.on //要执行则添加
                    && StringUtils.isNotEmpty(flow.getCron())){
                spiderJobManager.addJob(flow);
            }
        } else {  //为null，说明是插入操作
            String id = UUID.randomUUID().toString().replace("-", "");
            flow.setCreateDate(new Date());
            flow.setId(id);
            flowMapper.insert(flow);
        }
        //以上操作完成后，保存一个副本
        HistoryConfig config = new HistoryConfig();
        config.setConfig(flow.getConfig());
        config.setFlowId(flow.getId());
        config.setCreateTime(new Date());
        System.out.println(config);
        historyConfigService.save(config);
        return true;
    }

    public boolean updateLastExecuteTimeById(Date now, String fid) {
        return flowMapper.updateLastExecuteTimeById(now, fid);
    }

    public SpiderFlow selectById(String id) {
        SpiderFlow flow = flowMapper.selectById(id);
        if (flow != null && StringUtils.isNotEmpty(flow.getConfig())) {
            String config = flow.getConfig();
//            System.out.println("替换前:"+config);
            config = config.replace(singleQuotes, "'");
//            System.out.println("替换后:"+config);
            flow.setConfig(config);
        }
        return flow;
    }

    public boolean updateByConfig(String config, String flowId) {
        return flowMapper.updateConfigById(config, flowId);
    }

    public boolean updateCron(String id, String cron) {
        boolean updated = flowMapper.updateCron(id, cron);
        if(updated) {
            SpiderFlow flow = getById(id);
            if (CronEnableType.on== flow.getCronEnable() )
                startCron(id);
            return true;
        }
        return false;
    }

    public List<String> cronNextExecuteTime(String cron, int executeTimes) {
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .build();
        List<Date> dates = TriggerUtils.computeFireTimes((OperableTrigger) trigger, null, executeTimes);
        return dates.stream().map(MyDateUtil::format)
                .collect(Collectors.toList());
    }

    public boolean startCron(String id) {
        boolean exists = spiderJobManager.exists(id);
        if (exists) //如果有,则移除
            spiderJobManager.remove(id);
        SpiderFlow flow = this.selectById(id);
        flow.setCronEnable(CronEnableType.on); //直接设置 dao层没有flow对象状态
        Date nextExecuteTime = spiderJobManager.addJob(flow);
        logger.info("当前任务:{} ,开始执行时间为:{}",
                flow.getName(), MyDateUtil.format(nextExecuteTime));
        return flowMapper.updateCronStatus(id, "true");
    }

    public boolean stopCron(String id) {
        spiderJobManager.remove(id);
        return flowMapper.updateCronStatus(id, "false");
    }

    public boolean removeById(Serializable id) {
        String strId = (String) id;
        spiderJobManager.remove(strId);
        return super.removeById(id);
    }

}



// for循环中查询
//    public IPage<SpiderFlow> selectPages(Page<SpiderFlow> page, String name) {
//        LambdaQueryWrapper<SpiderFlow> wrapper = new LambdaQueryWrapper<>();
//        wrapper.like(StringUtils.isNotEmpty(name), SpiderFlow::getName, name)
//                .orderByDesc(SpiderFlow::getLastExecuteTime)
//                .orderByDesc(SpiderFlow::getCreateDate);
//        IPage<SpiderFlow> iPage = this.page(page, wrapper);
//        List<SpiderFlow> records = iPage.getRecords();
//        List<SpiderFlow> nRecords = new ArrayList<>(records.size());
//        records.forEach(flow -> {
//            SpiderFlowVo nFlow = new SpiderFlowVo();
//            String fid = flow.getId();
//            Integer allCnt = taskMapper.getAllCountByFlowId(fid);
//            Integer running = allCnt - taskMapper.getFinishedCountByFlowId(fid);
//            String rVall = running + "/" + allCnt;
//            BeanUtils.copyProperties(flow, nFlow);
//            //添加一个属性值
//            nFlow.setRunningAll(rVall);
//            nRecords.add(nFlow);
//        });
//        iPage.setRecords(nRecords);
//        return iPage;
//    }